#include <cstdlib>
#include <wx/socket.h>
#include "ScenariosManager.h"
#include <wx/dir.h>
#include "ScenariosControl.h"
#include "OsipProcess.h"
#include "app.h"
#include "aes.h"
#include <algorithm>

using namespace std;

wxString GetXmlNodeProp(xmlNodePtr ActionNode, const char* propname){
  wxString Method=wxT("");
  xmlChar *methodprop = xmlGetProp(ActionNode, (const xmlChar*)propname);
  if (methodprop){
    Method = wxString(wxConvUTF8.cMB2WC((const char*)methodprop),*wxConvCurrent);
    xmlFree(methodprop);
  }
  return Method;
}

extern int SendOsipMsg(osip_transaction_t *tr,osip_message_t *sip, char *host,int port, int out_socket);

bool Action_ScenarioFinish(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
    wxString reason = Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns);
    TermIns.OnScenarioEnd(reason==wxT("Succ"),reason);
    return true;
}

bool Action_ClearFinalMark(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
    TermIns.FinalMark=false;
    return true;
}

bool Action_PutHead(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
	    string  headname = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns,TermIns.pCallInfo->pCurSce);
	    string headvalue = Sce.GetPatamRealValue(ActionNode, "Param1",TermIns,TermIns.pCallInfo->pCurSce);
		if ((headname.size()>0) &&(headvalue.size()>0)){
			osip_message_set_header(pomt,headname.c_str(),headvalue.c_str());
			return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for PutHead!!"));
		}
	}
	else{
	    STT_TRACE(TermIns.Uid,TL_ERROR,_("Get Default Message Pointer fail!!"));
	}
	return false;
}

bool Action_StoreBody(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	wxString varname = Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns);
	if (varname.size()>0){
	    osip_message_t *pomt=evt->GetOsipMsgPtr();
	    if (pomt){
		wxString Value=wxT("");
		osip_body_t *body=NULL;
		osip_message_get_body(pomt,0,&body);
		if (body){
		  Value=wxString((body->body), *wxConvCurrent);
		}
		if ((TermIns.Varibles.find(varname) != TermIns.Varibles.end()) &&(!TermIns.Varibles[varname].IsEmpty())){
		  TermIns.Varibles[varname] = Value;
		}
		else{
		  TermIns.pCallInfo->Varibles[varname] = Value;
		}
		return true;
	    }
	    else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("Can not get osip message when Action_StoreHead"));
	    }
	}
	else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("StoreHead Without Param0 or Param1"));
	}
	return false;
}



bool Action_StoreHead(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	string headname = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
	wxString varname = Sce.GetPatamRealValueAsUnicode(ActionNode, "Param1",TermIns);
	string parname = Sce.GetPatamRealValue(ActionNode, "Param2",TermIns);
	string Idx = Sce.GetPatamRealValue(ActionNode, "Idx",TermIns);
	if ((headname.size()>0) &&(varname.size()>0)){
	    osip_message_t *pomt=evt->GetOsipMsgPtr();
	    if (pomt){
		wxString Value=wxT("");
		if (headname=="CallId"){
		    osip_call_id *p = osip_message_get_call_id(pomt);
		    if (p){
		        char* sp=NULL;
		        osip_call_id_to_str(p,&sp);
                Value=wxString(sp, *wxConvCurrent);
                osip_free(sp);
		    }
		}
		else if (headname=="CSeq"){
		    osip_cseq_t *pcseq = osip_message_get_cseq (pomt);
		    if (pcseq){
			Value=wxString((pcseq->number), *wxConvCurrent);
		    }
		}
		else if (headname=="Via"){
		  int idx=0;
		  if (Idx.size()>0){
			idx=atoi(Idx.c_str());
		  }
		  osip_via_t *pvia;
		  if (osip_message_get_via(pomt,idx,&pvia) == 0){
			if (parname.size()>0){
			  osip_uri_param_t* pvalue=NULL;
			  if (0==osip_via_param_get_byname(pvia,(char*)parname.c_str(),&pvalue)){
				Value= STT_LStr(pvalue->gvalue);
			  }
			}
		  }
		  else{
			char*from;
			if (osip_via_to_str(pvia,&from)==0){
			  Value = STT_LStr(from);
			  osip_free(from);
			}
		  }
		}
		else if (headname=="Contact"){
		    osip_contact_t *pcontact;
		    if (osip_message_get_contact(pomt,0,&pcontact) == 0){
		    	char *from;
			if (parname=="uri"){
			    	if (osip_uri_to_str(pcontact->url,&from)==0){
					Value = STT_LStr(from);
					osip_free(from);
				}
			}
			else{
			    	if (osip_contact_to_str(pcontact,&from)==0){
					Value = STT_LStr(from);
					osip_free(from);
				}
			}
		    }
		}
		else{
		    osip_header_t *cushead=NULL;
		    osip_message_header_get_byname(pomt,headname.c_str(),0,&cushead);
		    if (cushead){
			if (parname.size()>0){
			    Value=Sce.GetOsipHeadParamValueByName(cushead,parname.c_str());
			}
			else{
			    Value=wxString((cushead->hvalue), *wxConvCurrent);
			}
		    }
		}
		if (!Value.IsEmpty()){
		    //TermIns.SetVarible(varname,Value);
		    //wxString value = Sce.GetPatamRealValueAsUnicode(ActionNode, "Param1",TermIns);
		    if ((TermIns.Varibles.find(varname) != TermIns.Varibles.end()) &&(!TermIns.Varibles[varname].IsEmpty())){
			TermIns.Varibles[varname] = Value;
		    }
		    else{
			TermIns.pCallInfo->Varibles[varname] = Value;
		    }
		    return true;
		}
		else{
		    STT_TRACE(TermIns.Uid,TL_ERROR,wxString::Format(_("There is no head %s in osip message!"),STT_LStr(headname.c_str())));
		}
	    }
	    else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("Can not get osip message when Action_StoreHead"));
	    }
	}
	else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("StoreHead Without Param0 or Param1"));
	}
	return false;
}


bool Action_SetVarible(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	wxString name = Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns);
	if (name.size()>0){
		wxString value = Sce.GetPatamRealValueAsUnicode(ActionNode, "Param1",TermIns);
		if ((TermIns.Varibles.find(name) != TermIns.Varibles.end()) &&(!TermIns.Varibles[name].IsEmpty())){
			TermIns.Varibles[name] = value;
			STT_TRACE(TermIns.Uid,TL_MESSAGE,wxString::Format(wxT("Set Term Scope Varible %s to %s"),name.c_str(),value.c_str()));
		}
		else{
			TermIns.pCallInfo->Varibles[name] = value;
			STT_TRACE(TermIns.Uid,TL_MESSAGE,wxString::Format(wxT("Set Call Scope Varible %s to %s"),name.c_str(),value.c_str()));
		}
		return true;
	}
	else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("SetVarible Without Param0"));
	}
	return false;
}

bool Action_SetCallId(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
		  osip_call_id_t *callidPtr;
		  int status;
		  if((status = osip_call_id_init(&callidPtr)) != 0 ){
		    TermIns.Trace(TL_ERROR,_("call id failed!\n"));
		    return false;
		  }
		  if ((status = osip_call_id_parse(callidPtr, (const char*) uastr.c_str())) != 0)
		    {
		      TermIns.Trace(TL_ERROR,_("call id parse failed!\n"));
		      return false;
		    }
                  wxString CallId=wxString(uastr.c_str(), *wxConvCurrent);
                  if (TermIns.pCallInfo->exCallIds.Index(CallId) == wxNOT_FOUND){
                    //Since We Set it,it should be valid!
    		    TermIns.pCallInfo->exCallIds.push_back(CallId);
                  }
		  pomt->call_id = callidPtr;
		  return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetCallId!!"));
		}
	}
	return false;
}

bool Action_SetCseq(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
		  osip_cseq_t *cseqPtr;
		  int status;
		  if((status = osip_cseq_init(&cseqPtr)) != 0 ){
		    TermIns.Trace(TL_ERROR,_("seq init failed!\n"));
		    return false;
		  }
		  char *seqNumStr = (char *)osip_malloc(100);
		  strcpy(seqNumStr,uastr.c_str());
		  osip_cseq_set_number(cseqPtr, seqNumStr);
		  osip_cseq_set_method(cseqPtr, osip_strdup(pomt->sip_method));
		  pomt->cseq = cseqPtr;
		  return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetUserAgent!!"));
		}
	}
	return false;
}

bool Action_SetContact(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
  osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		string  expirestr = Sce.GetPatamRealValue(ActionNode, "expires",TermIns);
		string  qstr = Sce.GetPatamRealValue(ActionNode, "q",TermIns);
		if (uastr.size()>0){
		  if (0==osip_message_set_contact(pomt,uastr.c_str())){
			osip_contact_t *contact = (osip_contact_t*) osip_list_get(pomt->contacts,osip_list_size(pomt->contacts)-1);
			if (expirestr.size()>0){
			  if (contact){
				osip_contact_param_add(contact,osip_strdup("expires"),osip_strdup((char*)expirestr.c_str()));
			  }
			}
			if (qstr.size()>0){
			  if (contact){
				osip_contact_param_add(contact,osip_strdup("q"),osip_strdup((char*)qstr.c_str()));
			  }
			}
			return true;
		  }
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetMaxForward!!"));
		}
	}
	return false;
}

//this function not export in win32 version.so we redo it.
int
myosip_message_append_via (osip_message_t * sip, const char *hvalue)
{
  osip_via_t *via;
  int i;

  i = osip_via_init (&via);
  if (i != 0)
    return -1;
  i = osip_via_parse (via, hvalue);
  if (i != 0)
    {
      osip_via_free (via);
      return -1;
    }
  sip->message_property = 2;
  osip_list_add (sip->vias, via, 0);
  return 0;
}

bool Action_SetVia(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		string  insertflag = Sce.GetPatamRealValue(ActionNode, "DoInsert",TermIns);
		string  clearflag = Sce.GetPatamRealValue(ActionNode, "DoClear",TermIns);
		if (uastr.size()>0){
		  if (clearflag == "1"){
			//Clear All old Vias.
			if (pomt->vias){
			  osip_via_t *via = (osip_via_t *)osip_list_get(pomt->vias,0);
			  while (via != NULL){
				osip_via_free(via);
				osip_list_remove(pomt->vias,0);
				via = (osip_via_t *)osip_list_get(pomt->vias,0);
			  }
			}
		  }
		  if (insertflag == "1"){
			myosip_message_append_via(pomt,uastr.c_str());
		  }
		  else{
			osip_message_set_via(pomt,uastr.c_str());
		  }
		  return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetMaxForward!!"));
		}
	}
	return false;
}

bool Action_SetRoute(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
			osip_route_t *route=NULL;
			int i = osip_route_init (&route);
			if (i!=0){
				STT_TRACE(TermIns.Uid,TL_ERROR,_("Init Route record fail!!"));
				return false;
			}
			osip_uri_t* uri=NULL;
		    osip_uri_init(&uri);
			int status;
		    if ((status = osip_uri_parse(uri, (const char*) uastr.c_str())) != 0)
		    {
			  STT_TRACE(TermIns.Uid,TL_ERROR,_("uri parse failed!\n")+wxString(uastr.c_str(),*wxConvCurrent));
		      return false;
		    }

			route->url = uri;
			osip_list_add(pomt->routes, route, 0);
			return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetMaxForward!!"));
		}
	}
	return false;
}


bool Action_SetAuthorization(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string rsp = Sce.GetPatamRealValue(ActionNode, "response",TermIns);
		string auts;
		bool NeedAuts=false;
		if (rsp.size()==0)
		{
		    int rspret=TermIns.CaleResponse(rsp,auts);
		    if (rspret==2) NeedAuts=true;
		}
		else if (rsp=="-"){
		    rsp="";
		}

		if (NeedAuts){
		    string final="";
		    string  uastr = Sce.GetPatamRealValue(ActionNode, "AuthType",TermIns);
		    if (uastr.size()>0){
			final+=uastr;
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "username",TermIns);
		    if (uastr.size()>0){
			final=final+" username=\""+uastr+"\"";
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "realm",TermIns);
		    if (uastr.size()>0){
			final=final+", realm=\""+uastr+"\"";
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "nonce",TermIns);
		    if (uastr.size()==0) {
			uastr=TermIns.lastnonce;
		    }
		    else if (uastr=="-"){
			uastr="";
		    }
		    final=final+", nonce=\""+uastr+"\"";

		    uastr = Sce.GetPatamRealValue(ActionNode, "uri",TermIns);
		    if (uastr.size()>0){
			final=final+", uri=\""+uastr+"\"";
		    }

		    final=final+", auts=\""+auts+"\"";
		    osip_message_set_header(pomt,"Authorization",final.c_str());

		}
		else{
		    osip_authorization_t *aut;
		    osip_authorization_init (&aut);

		    if (rsp.size()>0){
			char *v = osip_strdup ((string("\"")+rsp+"\"").c_str());
			osip_authorization_set_response(aut, v);
		    }

		    string  uastr = Sce.GetPatamRealValue(ActionNode, "AuthType",TermIns);
		    if (uastr.size()>0){
			osip_authorization_set_auth_type (aut, osip_strdup (uastr.c_str()));
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "realm",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_realm(aut, v);
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "nonce",TermIns);
		    if (uastr.size()==0) {
			uastr=TermIns.lastnonce;
		    }
		    else if (uastr=="-"){
			uastr="";
		    }
		    char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
		    osip_authorization_set_nonce(aut, v);

		    uastr = Sce.GetPatamRealValue(ActionNode, "opaque",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_opaque(aut, v);
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "username",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_username(aut, v);
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "uri",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_uri(aut, v);
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "digest",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_opaque(aut, v);
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "cnonce",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_cnonce(aut, v);
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "message_qop",TermIns);
		    if (uastr.size()>0){
			osip_authorization_set_message_qop(aut, osip_strdup (uastr.c_str()));
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "nonce_count",TermIns);
		    if (uastr.size()>0){
			osip_authorization_set_nonce_count(aut, osip_strdup (uastr.c_str()));
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "algorithm",TermIns);
		    if (uastr.size()>0){
			osip_authorization_set_algorithm(aut, osip_strdup (uastr.c_str()));
		    }

		    osip_list_add (pomt->authorizations, aut, -1);
		}
		return true;

	}
	return false;
}

bool Action_SetProxyAuthorization(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string rsp = Sce.GetPatamRealValue(ActionNode, "response",TermIns);
		string auts;
		bool NeedAuts=false;
		if (rsp.size()==0)
		{
		    int rspret=TermIns.CaleResponse(rsp,auts);
		    if (rspret==2) NeedAuts=true;
		}
		else if (rsp=="-"){
		    rsp="";
		}

		if (NeedAuts){
		    string final="";
		    string  uastr = Sce.GetPatamRealValue(ActionNode, "AuthType",TermIns);
		    if (uastr.size()>0){
			final+=uastr;
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "username",TermIns);
		    if (uastr.size()>0){
			final=final+" username=\""+uastr+"\"";
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "realm",TermIns);
		    if (uastr.size()>0){
			final=final+", realm=\""+uastr+"\"";
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "nonce",TermIns);
		    if (uastr.size()==0) {
			uastr=TermIns.lastnonce;
		    }
		    else if (uastr=="-"){
			uastr="";
		    }
		    final=final+", nonce=\""+uastr+"\"";

		    uastr = Sce.GetPatamRealValue(ActionNode, "uri",TermIns);
		    if (uastr.size()>0){
			final=final+", uri=\""+uastr+"\"";
		    }

		    final=final+", auts=\""+auts+"\"";
		    osip_message_set_header(pomt,"Proxy-Authorization",final.c_str());

		}
		else{
		    osip_proxy_authorization_t *aut;
		    osip_proxy_authorization_init (&aut);

		    if (rsp.size()>0){
			char *v = osip_strdup ((string("\"")+rsp+"\"").c_str());
			osip_authorization_set_response(aut, v);
		    }

		    string  uastr = Sce.GetPatamRealValue(ActionNode, "AuthType",TermIns);
		    if (uastr.size()>0){
			osip_authorization_set_auth_type (aut, osip_strdup (uastr.c_str()));
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "realm",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_realm(aut, v);
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "nonce",TermIns);
		    if (uastr.size()==0) {
			uastr=TermIns.lastnonce;
		    }
		    else if (uastr=="-"){
			uastr="";
		    }
		    char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
		    osip_authorization_set_nonce(aut, v);

		    uastr = Sce.GetPatamRealValue(ActionNode, "opaque",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_opaque(aut, v);
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "username",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_username(aut, v);
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "uri",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_uri(aut, v);
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "digest",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_opaque(aut, v);
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "cnonce",TermIns);
		    if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_authorization_set_cnonce(aut, v);
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "message_qop",TermIns);
		    if (uastr.size()>0){
			osip_authorization_set_message_qop(aut, osip_strdup (uastr.c_str()));
		    }
		    uastr = Sce.GetPatamRealValue(ActionNode, "nonce_count",TermIns);
		    if (uastr.size()>0){
			osip_authorization_set_nonce_count(aut, osip_strdup (uastr.c_str()));
		    }

		    uastr = Sce.GetPatamRealValue(ActionNode, "algorithm",TermIns);
		    if (uastr.size()>0){
			osip_authorization_set_algorithm(aut, osip_strdup (uastr.c_str()));
		    }

		    osip_list_add (pomt->proxy_authorizations, aut, -1);
		}
		return true;

	}
	return false;
}


bool Action_SetWWWAuthenticate(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		osip_www_authenticate_t *w_auth;
		osip_www_authenticate_init (&w_auth);
		string  uastr = Sce.GetPatamRealValue(ActionNode, "AuthType",TermIns);
		if (uastr.size()>0){
			osip_www_authenticate_set_auth_type (w_auth, osip_strdup (uastr.c_str()));
		}
		uastr = Sce.GetPatamRealValue(ActionNode, "realm",TermIns);
		if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_www_authenticate_set_realm(w_auth, v);
		}

		uastr = Sce.GetPatamRealValue(ActionNode, "nonce",TermIns);
		if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_www_authenticate_set_nonce(w_auth, v);
		}

		uastr = Sce.GetPatamRealValue(ActionNode, "domain",TermIns);
		if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_www_authenticate_set_domain(w_auth, v);
		}

		uastr = Sce.GetPatamRealValue(ActionNode, "opaque",TermIns);
		if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_www_authenticate_set_opaque(w_auth, v);
		}

		uastr = Sce.GetPatamRealValue(ActionNode, "stale",TermIns);
		if (uastr.size()>0){
			osip_www_authenticate_set_stale(w_auth, osip_strdup (uastr.c_str()));
		}

		uastr = Sce.GetPatamRealValue(ActionNode, "algorithm",TermIns);
		if (uastr.size()>0){
			osip_www_authenticate_set_algorithm(w_auth, osip_strdup (uastr.c_str()));
		}

		uastr = Sce.GetPatamRealValue(ActionNode, "qop_options",TermIns);
		if (uastr.size()>0){
			char *v = osip_strdup ((string("\"")+uastr+"\"").c_str());
			osip_www_authenticate_set_qop_options(w_auth, v);
		}

		osip_list_add (pomt->www_authenticates, w_auth, -1);
		return true;

	}
	return false;
}

bool Action_SetAllow(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
			osip_message_set_allow(pomt,uastr.c_str());
			return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetMaxForward!!"));
		}
	}
	return false;
}

bool Action_SetExpire(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		const char* UaTag="expires";
		osip_header_t *dest;
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
			if (osip_message_header_get_byname(pomt,UaTag,0,&dest)>0){
				osip_free (dest->hvalue);
				dest->hvalue=osip_strdup(uastr.c_str());
			}
			else{
				osip_message_set_header(pomt,UaTag,uastr.c_str());
			}
			return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetMaxForward!!"));
		}
	}
	return false;
}

bool Action_SetMaxForward(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		const char* UaTag="Max-Forwards";
		osip_header_t *dest;
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
			if (osip_message_header_get_byname(pomt,UaTag,0,&dest)>0){
				osip_free (dest->hvalue);
				dest->hvalue=osip_strdup(uastr.c_str());
			}
			else{
				osip_message_set_header(pomt,UaTag,uastr.c_str());
			}
			return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetMaxForward!!"));
			//Sce.DumpConfig();
			//printf("\n");
			//TermIns.DumpVarible(wxT("All Varibles:"));
			//printf("\n");
			//wxGetApp().m_ScenariosManager->DefaultScenario->DumpConfig();
		}
	}
	return false;
}

bool Action_StoreTransaction(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_transaction_t *pott=evt->GetOsipTransPtr();
	if (pott){
		wxString uastr = Sce.GetPatamRealValueAsUnicode(ActionNode, "Name",TermIns);
		if (uastr.Length()>0){
			TermIns.pCallInfo->Transactions[uastr] = pott;
		    return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for StoreTransaction!!"));
		}
	}
	return false;
}

bool Action_StartTimer(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
  wxString name = Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns);
  string len = Sce.GetPatamRealValue(ActionNode, "Param1",TermIns);
  string FailOnExists = Sce.GetPatamRealValue(ActionNode, "FailOnExists",TermIns);
  string CleanOnEnd = Sce.GetPatamRealValue(ActionNode, "CleanOnEnd",TermIns);
  if (wxGetApp().RequestTimer(TermIns.Uid,atoi(len.c_str()),name,TermIns.pCallInfo->GetId())) {
      if (CleanOnEnd !="0"){
	  TermIns.pCallInfo->Timers.push_back(UidwxStringPair(TermIns.Uid,name).ToString());
      }
      if (wxGetApp().TimerNum()>(size_t)wxGetApp().MaxTimerNum){
	  wxGetApp().MaxTimerNum = wxGetApp().TimerNum();
	  TermIns.controller->TouchReport(_("Max Timer Num"),wxGetApp().MaxTimerNum);
      }
      return true;
  }
  return FailOnExists!="1";
}

bool Action_CancelTimer(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
  wxString name = Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns);
  string NoFail = Sce.GetPatamRealValue(ActionNode, "NoFail",TermIns);
  return wxGetApp().CancelTimer(TermIns.Uid,name) || (NoFail=="1");
}

bool Action_SetRegistState(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
    TermIns.SetRegisted(Sce.GetPatamRealValue(ActionNode, "Param0",TermIns) == "1");
    return true;
}

bool Action_SetUri(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
		    osip_uri_init(&(pomt->req_uri));
			int status;
		    if ((status = osip_uri_parse(pomt->req_uri, (const char*) uastr.c_str())) != 0)
		    {
			  STT_TRACE(TermIns.Uid,TL_ERROR,_("uri parse failed!\n")+wxString(uastr.c_str(),*wxConvCurrent));
		      return false;
		    }
		    return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetUri!!"));
		}
	}
	return false;
}

bool Action_SetTo(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
			osip_message_set_to(pomt,uastr.c_str());
			return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetUserAgent!!"));
		}
	}
	return false;
}

bool Action_SetVersion(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
			osip_message_set_version(pomt,osip_strdup(uastr.c_str()));
			return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetUserAgent!!"));
		}
	}
	return false;
}

bool Action_SetFrom(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
  osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
  if (pomt){
    string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
    string  tagstr = Sce.GetPatamRealValue(ActionNode, "Tag",TermIns);
    if (uastr.size()>0){
      if (osip_message_set_from(pomt,uastr.c_str())!=0){
		STT_TRACE(TermIns.Uid,TL_ERROR,wxString::Format(_("Fail To SetFrom to %s!!"),STT_LStr(uastr.c_str())));
      }
      else{
		if (tagstr.size()>0){
		  if (tagstr != "-"){
			osip_from_set_tag (pomt->from, osip_strdup(tagstr.c_str()));
		  }
		  return true;
		}
		else{
		  osip_generic_param_t *tag;
		  osip_to_get_tag (pomt->from, &tag);
		  
		  char* tmp = (char *) osip_malloc (33);
		  unsigned int number = osip_build_random_number ();
		  sprintf (tmp, "%u", number);
		  osip_from_set_tag (pomt->from, tmp);
		  return true;
		}
      }
    }
    else{
      STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetFrom!!"));
    }
  }
  return false;
}

bool Action_SetUserAgent(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
	if (pomt){
		const char* UaTag="User-Agent";

		string  uastr = Sce.GetPatamRealValue(ActionNode, "Param0",TermIns);
		if (uastr.size()>0){
		  osip_message_set_header(pomt,UaTag,uastr.c_str());
		  return true;
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetUserAgent!!"));
		}
	}
	return false;
}

bool Action_SetBody(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
    osip_message_t *pomt=TermIns.GetCurrentMsg(NULL);
    if (pomt){
	wxString BodyOrig=Sce.GetPatamRealValueAsUnicode(ActionNode, "",TermIns);
	wxString CntType=Sce.GetPatamRealValueAsUnicode(ActionNode, "CntType",TermIns);
	wxString ParamCount=Sce.GetPatamRealValueAsUnicode(ActionNode, "ParamCount",TermIns);
	if (ParamCount.IsNumber()){
	    long pcount=0;
	    ParamCount.ToLong(&pcount);
	    for (int i=1;i<=pcount;i++){
		char paraname[100];
		sprintf(paraname,"Param%d",i);
		wxString ParamValue=Sce.GetPatamRealValueAsUnicode(ActionNode, paraname,TermIns);
		BodyOrig.Replace(wxT("%s"),ParamValue,false);
	    }
	}
        BodyOrig.Replace(wxT("\r\n"),wxT("\n"));
        BodyOrig.Replace(wxT("\n"),wxT("\r\n"));
	string  uastr = Sce.Conv2Std(BodyOrig);
	string cnttype="text/xml";
	if (!CntType.IsEmpty()){
	    cnttype = Sce.Conv2Std(CntType);
	}
	if (uastr.size()>0){
	    osip_message_set_content_type(pomt,cnttype.c_str());
	    osip_message_set_body(pomt,uastr.c_str(),uastr.size());
	    return true;
	}
	else{
	    STT_TRACE(TermIns.Uid,TL_ERROR,_("Invalid Param for SetUserAgent!!"));
	}
    }
    return false;
}

bool Action_NameDialog(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
    osip_message_t *pomt=TermIns.GetCurrentMsg(evt);
    if (pomt){
	int Index;
	wxString DialogName=Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns);
	osip_dialog_t* dialog=TermIns.GetDialog(pomt,&Index);
	if (!dialog){
	    if (!MSG_TEST_CODE(pomt,0)){
		osip_dialog_init_as_uac(&dialog, pomt);
		Index=TermIns.AddDialog(dialog);
	    }
	}
	if (dialog){
	    if (!DialogName.IsEmpty()){
		wxString name = DialogName;
		wxString value=wxString::Format(wxT("%d"),Index);
		if ((TermIns.Varibles.find(name) != TermIns.Varibles.end()) &&(!TermIns.Varibles[name].IsEmpty())){
		    TermIns.Varibles[name] = value;
		}
		else{
		    TermIns.pCallInfo->Varibles[name] = value;
		}

		return true;
	    }
	    else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("Name Dialog Param0 invalid!!"));
	    }
	}
	else{
	    STT_TRACE(TermIns.Uid,TL_ERROR,_("Get DialogId Fail!!"));
	}
    }
    return false;
}

bool Action_ForceRemotePort(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
    wxString DialogName=Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns);
    if (DialogName.IsNumber()){
	long v=TermIns.RemotePort;
	DialogName.ToLong(&v);
	TermIns.RemotePort = v;
    }
    else{
	STT_TRACE(TermIns.Uid,TL_ERROR,wxString::Format(_("%s Is not a digits!!"),DialogName.c_str()));
	return false;
    }
    return true;
}


bool Action_DoDebug(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
  wxString V=Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns);
  STT_TRACE(TermIns.Uid,TL_MESSAGE,V);
  return true;
}

bool Action_DoStatistic(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
    wxString V=Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns,TermIns.pCallInfo->pCurSce);
  TermIns.controller->TouchReportStatistic(V);
  //STT_TRACE(TermIns.Uid,TL_MESSAGE,V);
  return true;
}


bool Action_DoTrace(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
    wxString V=Sce.GetPatamRealValueAsUnicode(ActionNode, "Param0",TermIns,TermIns.pCallInfo->pCurSce);
  TermIns.pCallInfo->LogString(V);
  //STT_TRACE(TermIns.Uid,TL_MESSAGE,V);
  return true;
}


int
osip_from_clone_without_totag (const osip_from_t * from, osip_from_t ** dest)
{
  int i;
  osip_from_t *fr;

  *dest = NULL;
  if (from == NULL)
    return -1;

  i = osip_from_init (&fr);
  if (i != 0)                   /* allocation failed */
    return -1;
  if (from->displayname != NULL)
    fr->displayname = osip_strdup (from->displayname);

  if (from->url != NULL)
    {
      i = osip_uri_clone (from->url, &(fr->url));
      if (i != 0)
        {
          osip_from_free (fr);
          return -1;
        }
    }

  {
    int pos = 0;
    osip_generic_param_t *u_param;
    osip_generic_param_t *dest_param;

    while (!osip_list_eol (from->gen_params, pos))
      {
        u_param = (osip_generic_param_t *) osip_list_get (from->gen_params, pos);
	if (strcmp(u_param->gname,"tag")!=0){
	    i = osip_generic_param_clone (u_param, &dest_param);
	    if (i != 0)
		{
		    osip_from_free (fr);
		    return -1;
		}
	    osip_list_add (fr->gen_params, dest_param, -1);
	}
        pos++;
      }
  }
  *dest = fr;
  return 0;
}

int
osip_to_clone_without_totag (const osip_to_t * to, osip_to_t ** dest)
{
  return osip_from_clone_without_totag ((osip_from_t *) to, (osip_from_t **) dest);
}

int get_ack_dest(osip_message_t* ack, wxString& addr, int * rport){
    osip_route_t *route=NULL;
    int port = 5060;
    osip_message_get_route (ack, 0, &route);
    osip_uri_t *uri = osip_message_get_uri(ack);
    if (route != NULL && route->url != NULL){
          osip_uri_param_t *lr_param;
          osip_uri_uparam_get_byname (route->url, "lr", &lr_param);
          if (lr_param == NULL)   {
                  /* using uncompliant proxy: destination is the request-uri */
                  route = NULL;
          }
          if (route != NULL) {
              uri = route->url;
          }
    }
    if (uri){
          if (uri->port != NULL)   port = osip_atoi (uri->port);
          addr=STT_LStr(uri->host);
    }
    *rport = port;
    return 0;
}


bool Action_Send(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode)
{
	bool IsRequest=false;
	bool IsAck=false;

	//Sce.DumpConfig();
	//printf("\n");
	//TermIns.DumpVarible(wxT("All Varibles:"));
	//printf("\n");
	//wxGetApp().m_ScenariosManager.DefaultScenario->DumpConfig();

	xmlChar* methodprop = xmlGetProp(ActionNode, (const xmlChar*)"Method");
	wxString Method = wxString(wxConvUTF8.cMB2WC((const char*)methodprop),*wxConvCurrent);
	wxString MsgType = GetXmlNodeProp(ActionNode, "MsgType");
	//wxString MsgType = wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent);
	xmlChar *statuscode = xmlGetProp(ActionNode, (const xmlChar*)"StateCode");
	wxString Trans = GetXmlNodeProp(ActionNode, "Transaction");
	//wxString Trans = wxString(wxConvUTF8.cMB2WC((const char*)strans),*wxConvCurrent);
	wxString SwapFromTo = GetXmlNodeProp(ActionNode, "SwapFromTo");

	//printf("Send Action: Methord:%s Type:%s",(const char*)methodprop, (const char*)nodeprop);

	if (MsgType.CmpNoCase(wxT("Request"))==0){
		IsRequest = TRUE;
	}
	else if (MsgType.CmpNoCase(wxT("ACK"))==0){
		IsAck = TRUE;
	}

	osip_message_t *MsgPtr;
	if ((!IsRequest) &&(!evt)) return false;
	osip_message_t *request=NULL;
	osip_transaction_t *trans=NULL;
	if (!IsRequest){
		if (Trans.Length()>0){
		    if (TermIns.pCallInfo->Transactions.find(Trans)!=TermIns.pCallInfo->Transactions.end()){
			trans = TermIns.pCallInfo->Transactions[Trans];
		    }
		    if (!trans){
			STT_TRACE(TermIns.Uid,TL_ERROR, wxString::Format(_("Invalid Transaction Param %s!"),Trans.c_str()));
			return false;
		    }
		    if (!wxGetApp().AllTranses.IsAlive(trans)){
		      STT_TRACE(TermIns.Uid,TL_ERROR, wxString::Format(_("Invalid Transaction Param %s for %08X!"),Trans.c_str(),trans));
			return false;
		    }
		}
		else{
			trans=evt->GetOsipTransPtr();
			if ((!IsAck)&&(!trans)) return false;
		}
		if ((!IsAck) && trans->orig_request->to/*just add some safe check*/ ){
			request = trans->orig_request;
		}
		else{
		    request = evt->GetOsipMsgPtr();
		}
		if (!request) return false;
	}
	int status;
	if((status = osip_message_init(&MsgPtr)) != 0){
		STT_TRACE(TermIns.Uid,TL_ERROR,_("Can't init message!\n"));
		return false;
	}

	if ((IsRequest)|| (IsAck)){
		if (IsRequest){
			osip_message_set_method(MsgPtr, osip_strdup((const char*)methodprop));
		}
		else{
			osip_message_set_method(MsgPtr, osip_strdup("ACK"));
		}
		osip_message_set_status_code(MsgPtr, 0);
		osip_message_set_reason_phrase(MsgPtr, NULL);
		if (IsAck){
			if (request->from) osip_from_clone (request->from, &(MsgPtr->from));
			if (request->to) osip_to_clone (request->to, &(MsgPtr->to));
			if (request->call_id) osip_call_id_clone (request->call_id, &(MsgPtr->call_id));
			if (request->cseq) osip_cseq_clone (request->cseq, &(MsgPtr->cseq));
			osip_free (MsgPtr->cseq->method);
			MsgPtr->cseq->method = osip_strdup ("ACK");
			//User Should Set Ack Msg"s Uri and Via
		}
	}
	else{
		osip_message_set_method (MsgPtr, NULL);
		osip_message_set_uri (MsgPtr, NULL);
		int scode=atoi((const char*)statuscode);
		xmlFree(statuscode);
		osip_message_set_status_code(MsgPtr, scode);
		char *tmp = osip_strdup(osip_message_get_reason (scode));
		if (tmp == NULL){
			osip_message_set_reason_phrase (MsgPtr, osip_strdup ("Unknown status code"));
		}
		else {
			osip_message_set_reason_phrase (MsgPtr, tmp);
		}

		osip_generic_param_t *tag;
		if (request->to) osip_to_clone (request->to, &(MsgPtr->to));
		osip_to_get_tag (MsgPtr->to, &tag);
		if (!tag){/*Use the old to tag if gives dialog! */
		  string totag = Sce.GetPatamRealValue(ActionNode, "ToTag",TermIns);
		  if (totag != "-"){
		    tmp = (char *) osip_malloc (33);
		    if ((totag.size()>0) &&(totag.size()<30)){
			  strcpy(tmp,totag.c_str());
		    }
		    else{
			  unsigned int number = osip_build_random_number ();
			  sprintf (tmp, "%u", number);
		    }
		    osip_to_set_tag (MsgPtr->to, tmp);
		    if (request->to) osip_to_free(request->to);
		    osip_to_clone(MsgPtr->to,&(request->to));
		  }
		}
		osip_from_clone (request->from, &(MsgPtr->from));

		int pos = 0;
		while (!osip_list_eol (request->vias, pos))
		{
		      osip_via_t *via;
		      osip_via_t *via2;

		      via = (osip_via_t *) osip_list_get (request->vias, pos);
		      int i = osip_via_clone (via, &via2);
		      if (i != -0){
				TermIns.Trace(TL_ERROR,_("VIA Clone fail!\n"));
		  	    osip_message_free(MsgPtr);
				return false;
		      }
		      osip_list_add (MsgPtr->vias, via2, -1);
		      pos++;
		}

		pos = 0;
		while (!osip_list_eol (request->record_routes, pos))
		{
		      osip_record_route_t *rr1;
		      osip_record_route_t *rr2;

		      rr1 = (osip_record_route_t *) osip_list_get (request->record_routes, pos);
		      int i = osip_record_route_clone (rr1, &rr2);
		      if (i != -0){
				TermIns.Trace(TL_ERROR,_("Record Route Clone fail!\n"));
				osip_message_free(MsgPtr);
				return false;
		      }
		      osip_list_add (MsgPtr->record_routes, rr2, -1);
		      pos++;
		}

		if (request->call_id) osip_call_id_clone (request->call_id, &(MsgPtr->call_id));
		if (request->cseq) osip_cseq_clone (request->cseq, &(MsgPtr->cseq));
	}

	if (methodprop){
	  xmlFree(methodprop);\
	}


	TermIns.ToSend = MsgPtr;
	TermIns.pCallInfo->SendRuleLineNo=xmlGetLineNo(ActionNode);
	if (!Sce.ExecuteSendRule(TermIns,evt)){
	  STT_TRACE(TermIns.Uid,TL_ERROR,_("Execute Send rule Fail!!"));
	  osip_message_free(MsgPtr);
	  return false;
	}
	if ((wxGetApp().m_ScenariosManager->DefaultScenario) &&(Sce.GetIdentifier() != wxT("-")) && (Sce.GetRunDefaultRule()) ){
	  if (!wxGetApp().m_ScenariosManager->DefaultScenario->ExecuteSendRule(TermIns,evt)){
	    STT_TRACE(TermIns.Uid,TL_ERROR,_("Execute Default Send rule Fail!!"));
	    osip_message_free(MsgPtr);
	    return false;
	  }
	}
	TermIns.ToSend = NULL; //Ok,Done. Erase it.
	TermIns.pCallInfo->SendRuleLineNo=-1;

	if (!IsRequest){
	    if (MSG_TEST_CODE(MsgPtr,0)){
		STT_TRACE(TermIns.Uid,TL_ERROR,_("As a response, you should give a usable reason code!!"));
		osip_message_free(MsgPtr);
		return false;
	    }

	    xmlChar *dialogprop = xmlGetProp(ActionNode, (const xmlChar*)"DialogName");
	    //if (MSG_IS_RESPONSE_FOR(MsgPtr, "INVITE")&& (MSG_TEST_CODE(MsgPtr, 183))){
	    if ((dialogprop) &&(!MSG_TEST_CODE(MsgPtr, 0))){
		osip_dialog_t *dialog;
		dialog = TermIns.GetDialog(MsgPtr);
		if (dialog==NULL) //NO EXISTING DIALOG
		    {
			osip_dialog_init_as_uas(&dialog, request, MsgPtr);
			//osip_dialog_update_route_set_as_uas
			int index=TermIns.AddDialog(dialog);

			if (dialogprop){
			  wxString Dialog = wxString(wxConvUTF8.cMB2WC((const char*)dialogprop),*wxConvCurrent);
			  xmlFree(dialogprop);
			  TermIns.SetVaribleValue(Dialog,wxString::Format(wxT("%d"),index));
			}
		    }
	    }
	    /*if (MSG_IS_RESPONSE_FOR(MsgPtr, "SUBSCRIBE")&& (MSG_TEST_CODE(MsgPtr, 200))){
		osip_dialog_t *dialog;
		dialog = TermIns.GetDialog(MsgPtr);
		if (dialog==NULL) //NO EXISTING DIALOG
		    {
			osip_dialog_init_as_uas(&dialog, request, MsgPtr);
			//osip_dialog_update_route_set_as_uas
			int index=TermIns.AddDialog(dialog);
			xmlChar *dialogprop = xmlGetProp(ActionNode, (const xmlChar*)"DialogName");
			if (dialogprop){
			  wxString Dialog = wxString(wxConvUTF8.cMB2WC((const char*)dialogprop),*wxConvCurrent);
			  xmlFree(dialogprop);
			  TermIns.SetVaribleValue(Dialog,wxString::Format(wxT("%d"),index));
			}
		    }
		    }*/

	}

	{
	    osip_dialog_t* sipdialog=NULL;

	    /*After Execute all the send rule, Some key field in dialog need be update,if it is in a dialog */
	    xmlChar *dialogprop = xmlGetProp(ActionNode, (const xmlChar*)"Dialog");
	    if (dialogprop){
		    wxString Dialog = wxString(wxConvUTF8.cMB2WC((const char*)dialogprop),*wxConvCurrent);
			STT_TRACE(TermIns.Uid,TL_WARNING,wxString::Format(_("Dialog Is %s"),Dialog.c_str()));
		    xmlFree(dialogprop);
			if (Dialog != wxT("-")){
			  wxString DialogId=TermIns.GetVaribleValue(Dialog);			
			  if (DialogId.IsNumber()){
				long dialogid=TermIns.DialogNum();
				DialogId.ToLong(&dialogid);
				if ((dialogid>=0) &&(dialogid<TermIns.DialogNum())){
				  sipdialog=TermIns.DialogItem(dialogid);
				  STT_TRACE(TermIns.Uid,TL_WARNING,_("User Gives dialog!"));
				}
			  }
			}
	    }
	    else{
		  if ((IsRequest)|| (IsAck)){
		    /* Get dialog from the request response event */
		    if (evt->GetEvtType()==STTEVT_OSIP_EVENT){
			  osip_message_t* sip=evt->GetOsipMsgPtr();
			  sipdialog=TermIns.GetDialog(sip);
			  STT_TRACE(TermIns.Uid,TL_WARNING,_("Assign Dialog by event sip message!"));
		    }
		  }
	    }
	    if (sipdialog){
		  if (osip_list_size(sipdialog->route_set)>0){
		    /* Update routes in sip message with which in the dialog */
		    while (!osip_list_eol (MsgPtr->routes, 0))
			{
			    osip_record_route_t *rr1;

			    rr1 = (osip_record_route_t *) osip_list_get (MsgPtr->routes, 0);
			    osip_route_free(rr1);
			    osip_list_remove(MsgPtr->routes,0);
			}

		    if (sipdialog->type==CALLER){
			int pos = osip_list_size(sipdialog->route_set)-1;
			while (!osip_list_eol (sipdialog->route_set, pos))
			    {
				osip_record_route_t *rr1;
				osip_record_route_t *rr2;

				rr1 = (osip_record_route_t *) osip_list_get (sipdialog->route_set, pos);

				int i = osip_record_route_clone (rr1, &rr2);
				if (i != -0){
				    osip_message_free(MsgPtr);
				    return false;
				}
				osip_list_add (MsgPtr->routes, rr2, -1);
				pos--;
				if (pos<0) break;
			    }
		    }
		    else{
			int pos = 0;
			while (!osip_list_eol (sipdialog->route_set, pos))
			    {
				osip_record_route_t *rr1;
				osip_record_route_t *rr2;

				rr1 = (osip_record_route_t *) osip_list_get (sipdialog->route_set, pos);

				int i = osip_record_route_clone (rr1, &rr2);
				if (i != -0){
				    osip_message_free(MsgPtr);
				    return false;
				}
				osip_list_add (MsgPtr->routes, rr2, -1);
				pos++;
			    }
		    }
		}

        /*Update CallId field*/
        if (MsgPtr->call_id){
            osip_call_id_free(MsgPtr->call_id);
        }
	    osip_call_id_t *callidPtr;
		int status;
		if((status = osip_call_id_init(&callidPtr)) != 0 ){
				    osip_message_free(MsgPtr);
				    return false;
		  }
		  if ((status = osip_call_id_parse(callidPtr, sipdialog->call_id)) != 0)  {
				    osip_message_free(MsgPtr);
				    return false;
		    }
		MsgPtr->call_id = callidPtr;

		/*Update From and To Tag with which in dialog*/
		if (MsgPtr->from){
		    osip_from_free(MsgPtr->from);
		}
		if (MsgPtr->to){
		    osip_to_free(MsgPtr->to);
		}

		osip_uri_param_t *p=NULL;
		osip_to_get_tag(sipdialog->remote_uri,&p);
		if  (((sipdialog->type == CALLER)&&(SwapFromTo!=wxT("1")))
			 ||((sipdialog->type == CALLEE)&&(SwapFromTo==wxT("1")))){
		  osip_from_clone (sipdialog->local_uri, &(MsgPtr->from));
		  osip_to_clone (sipdialog->remote_uri, &(MsgPtr->to));
		}
		else{
		  osip_to_clone (sipdialog->local_uri, &(MsgPtr->to));
		  osip_from_clone (sipdialog->remote_uri, &(MsgPtr->from));
		}
	    }

	}

	string totag = Sce.GetPatamRealValue(ActionNode, "ToTag",TermIns);
	if ((totag.size()>0) &&(totag.size()<30)){
	    if (MsgPtr->to){
		osip_to_t *tmpto;
		osip_to_clone_without_totag(MsgPtr->to,&tmpto);
		osip_to_free(MsgPtr->to);
		MsgPtr->to = tmpto;
	    }
	    if (totag!="-"){
		char* tmp = (char *) osip_malloc (33);
		strcpy(tmp,totag.c_str());
		osip_to_set_tag (MsgPtr->to, tmp);
	    }
	}

	TermIns.GetController().TouchReport(STT_MSG_OUTGOING,MsgPtr);
	if (xmlGetProp(ActionNode, (const xmlChar*)"CheckValid")){
        int CheckUid=GetUidFromSipMsg(MsgPtr,STT_MSG_OUTGOING);
        TermControl *TermIns = wxGetApp().GetTermIns(CheckUid);
        if ((!TermIns) || (!TermIns->IsInThisCall())){
            STT_TRACE(-1,TL_ERROR,wxString::Format(_("Msg Check Return Fail,Not in this call:%d %d %d!!"),TermIns->Uid,
                    TermIns->pCallInfo->UserIndexStart,TermIns->pCallInfo->UsedTermNum));
            osip_message_free(MsgPtr);
            return false;
        }
	}

	//If direct send message.
	wxString Direct = GetXmlNodeProp(ActionNode, "DirectSend");
	if ((IsAck) || (Direct == wxT("1"))){
	    int port=-1;
	    wxString addr=wxT("");
	    get_ack_dest(MsgPtr,addr,&port);
	    if (addr.IsEmpty()){
            long remoteport=5060;
            wxString SsPort=TermIns.GetVaribleValue(wxT("SSPort"));
            if (SsPort.IsEmpty()){
                SsPort=Sce.GetConfigValue(wxT("SSPort"));
            }
            if (SsPort.IsNumber()){
                SsPort.ToLong(&remoteport);
            }
            port = remoteport;
            addr = Sce.GetConfigValue(wxT("Proxy_Address"));
	    }

	    return SendOsipMsg(NULL,MsgPtr,(char*)Sce.Conv2Std(addr).c_str(),
				   port,0)==0;
	}

	osip_transaction_t *transactionPtr=NULL;
	if (IsRequest){
		osip_fsm_type_t   transactionType=NICT;

		if (MSG_IS_INVITE(MsgPtr)){
			transactionType=ICT;
		}

		if ( (status = osip_transaction_init(&transactionPtr,transactionType,wxGetApp().osip,MsgPtr)) != 0 ){
			STT_TRACE(TermIns.Uid, TL_ERROR,_("Failed to init transaction!"));
			osip_message_free(MsgPtr);
			return false;
		}
		STT_TRACE(TermIns.Uid, TL_MESSAGE,wxString::Format(_("New Transaction Init Succ with:%p"),transactionPtr));

		osip_transaction_set_your_instance(transactionPtr,&TermIns);
		TermIns.GetController().AddTransaction(transactionPtr);
	        wxGetApp().AllTranses.AddTrans(transactionPtr);

		if (!Trans.IsEmpty()){
		    TermIns.pCallInfo->Transactions[Trans] = transactionPtr;
		}

	}
	else{
		transactionPtr = trans;
	}

	if (!transactionPtr){
		STT_TRACE(TermIns.Uid, TL_ERROR,_("There is no transaction avilible!!"));
		osip_message_free(MsgPtr);
		return false;
	}

	osip_event_t       *sipeventPtr;
	if((sipeventPtr = osip_new_outgoing_sipmessage(MsgPtr)) == NULL){
		TermIns.Trace(TL_ERROR,_("Can't allocate message!"));
		osip_message_free(MsgPtr);
		return false;
	}

	sipeventPtr->transactionid =  transactionPtr->transactionid;
	if((status = osip_message_force_update(MsgPtr)) != 0){
		TermIns.Trace(TL_ERROR,_("Failed force update!"));
		osip_message_free(MsgPtr);
		return false;
	}

	if((status = osip_transaction_add_event(transactionPtr, sipeventPtr)) != 0){
		TermIns.Trace(TL_ERROR,_("Can't add event!"));
		osip_message_free(MsgPtr);
		return false;
	}
	return true;

}

WX_DECLARE_STRING_HASH_MAP(SttActionCallback, ActionDriverHash);
ActionDriverHash gSttActionDrivers;
//SttActionDriver gSttActionDrivers[]={
void InitActionDrivers(void){
	gSttActionDrivers[wxT("Send")]=Action_Send;
	gSttActionDrivers[wxT("PutHead")] =Action_PutHead;
	gSttActionDrivers[wxT("SetRegistState")]=Action_SetRegistState;
	gSttActionDrivers[wxT("SetUserAgent")] =Action_SetUserAgent;
	gSttActionDrivers[wxT("SetFrom")] = Action_SetFrom;
	gSttActionDrivers[wxT("SetCseq")] =Action_SetCseq;
	gSttActionDrivers[wxT("SetMaxForward")] =Action_SetMaxForward;
	gSttActionDrivers[wxT("SetVia")] =Action_SetVia;
	gSttActionDrivers[wxT("SetRoute")]=Action_SetRoute;
	gSttActionDrivers[wxT("SetContact")]=Action_SetContact,
	gSttActionDrivers[wxT("SetExpire")]=Action_SetExpire;
	gSttActionDrivers[wxT("SetVarible")]=Action_SetVarible;
	gSttActionDrivers[wxT("StoreHead")] = Action_StoreHead;
	gSttActionDrivers[wxT("StoreBody")]=Action_StoreBody;
	gSttActionDrivers[wxT("SetUri")] = Action_SetUri;
	gSttActionDrivers[wxT("StartTimer")] =Action_StartTimer;
	gSttActionDrivers[wxT("CancelTimer")]=Action_CancelTimer;
	gSttActionDrivers[wxT("StoreTransaction")]=Action_StoreTransaction;
	gSttActionDrivers[wxT("SetTo")]=Action_SetTo;
	gSttActionDrivers[wxT("ForceRemotePort")]=Action_ForceRemotePort;
	gSttActionDrivers[wxT("SetVersion")]=Action_SetVersion;
	gSttActionDrivers[wxT("SetCallId")]=Action_SetCallId;
	gSttActionDrivers[wxT("SetAllow")]=Action_SetAllow;
	gSttActionDrivers[wxT("SetBody")]=Action_SetBody;
	gSttActionDrivers[wxT("SetAuthorization")]=Action_SetAuthorization;
	gSttActionDrivers[wxT("SetWWWAuthenticate")]=Action_SetWWWAuthenticate;
	gSttActionDrivers[wxT("ScenarioFinish")]=Action_ScenarioFinish;
	gSttActionDrivers[wxT("NameDialog")]=Action_NameDialog;
	gSttActionDrivers[wxT("DoDebug")]=Action_DoDebug;
	gSttActionDrivers[wxT("DoTrace")]=Action_DoTrace;
	gSttActionDrivers[wxT("DoStatistic")]=Action_DoStatistic;
	gSttActionDrivers[wxT("ClearFinalMark")]=Action_ClearFinalMark;
	gSttActionDrivers[wxT("SetProxyAuthorization")]=Action_SetProxyAuthorization;
}

bool Condition_HasHead(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(evt);
	if (!pomt) return false;
	string  nodeprop = Sce.GetPatamRealValue(CondNode, "Param0",TermIns);
	if (nodeprop.size()>0){
		if (strcmp(nodeprop.c_str(),"Authorization")==0){
			osip_authorization_t *unused;
			return osip_message_get_authorization(pomt,0,&unused) != -1;
		}
		else{
		  osip_header_t *ph=NULL;
		  return osip_message_header_get_byname(pomt,nodeprop.c_str(),0,&ph)>=0;
		}
	}
	return false;
}

bool Condition_IsAck(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(evt);
	if (!pomt) return false;
	return (MSG_IS_ACK(pomt));
}

bool Condition_IsRequest(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(evt);
	if (!pomt) return false;
	string  nodeprop = Sce.GetPatamRealValue(CondNode, "Param0",TermIns);
	if (nodeprop.size()>0){
		if (!MSG_IS_REQUEST(pomt)) return false;
		return ((pomt->sip_method) && (0==strcmp(pomt->sip_method,nodeprop.c_str())));
	}
	else{
		return (MSG_IS_REQUEST(pomt) && (!MSG_IS_ACK(pomt)));
	}
	return false;
}

bool Condition_IsResponseFor(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(evt);
	if (!pomt) return false;
	string  nodeprop = Sce.GetPatamRealValue(CondNode, "Param0",TermIns);
	if (nodeprop.size()>0){
		return MSG_IS_RESPONSE_FOR(pomt,nodeprop.c_str());
	}
	else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("IsResponseFor Without Param0"));
	}
	return false;
}

bool Condition_IsVaribleEqual(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){

	wxString name = Sce.GetPatamRealValueAsUnicode(CondNode, "Param0",TermIns);
	if (name.size()>0){
		wxString value = Sce.GetPatamRealValueAsUnicode(CondNode, "Param1",TermIns);
		wxString RValue=TermIns.GetVaribleValue(name);
		//if (TermIns.Varibles.find(name) != TermIns.Varibles.end()){
		//	return TermIns.Varibles[name] == value;
		//}
		//return TermIns.pCallInfo->Varibles[name] == value;
		//STT_TRACE(TermIns.Uid,TL_ERROR,wxString(_("IsVaribleEqual: "))+name+wxT(" ")+value+wxT(" ")+RValue);
		return RValue==value;
	}
	else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("IsVaribleEqual Without Param0"));
	}
	return false;
}

bool Condition_IsRspStateEqual(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
	osip_message_t *pomt=TermIns.GetCurrentMsg(evt);
	if (!pomt) return false;
	string  nodeprop = Sce.GetPatamRealValue(CondNode, "Param0",TermIns);
	if (nodeprop.size()>0){
		return MSG_TEST_CODE(pomt,atoi(nodeprop.c_str()));
	}
	else{
		STT_TRACE(TermIns.Uid,TL_ERROR,_("IsRspStateEqual Without Param0"));
	}
	return false;
}

bool Condition_IsEventNameEqual(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
  wxString  nodeprop = Sce.GetPatamRealValueAsUnicode(CondNode, "Param0",TermIns);
  if (nodeprop==wxT("ScenarioStarted")){
  	return evt->GetEvtType() == STTEVT_CASE_START;
  }
  else if (nodeprop==wxT("TermStateChange")){
  	return evt->GetEvtType() == STTEVT_TERM_REGSTATE_CHANGE;
  }
  return false;
}

bool Condition_IsUidEqual(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
  wxString  nodeprop = Sce.GetPatamRealValueAsUnicode(CondNode, "Param0",TermIns);
  long tmpUid=-2;
  if (nodeprop.IsNumber()){
      nodeprop.ToLong(&tmpUid);
  }
  return (TermIns.Uid % MAX_TERM_NUM) ==(tmpUid % MAX_TERM_NUM);
}

bool Condition_IsAllTermRegisted(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
    if (TermIns.pCallInfo){
  	for (int i=0;i<Sce.GetTermNumNeeded();i++){
	    if (!TermIns.GetController().GetTermCtrl(i+TermIns.pCallInfo->UserIndexStart)->IsRegisted()){
		return false;
	    }
  	}
	return true;
    }
    return false;
}

bool Condition_IsTimerNameEqual(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
  if (evt->GetEvtType() == STTEVT_TIMEROUT_EVENT){
    wxString  nodeprop = Sce.GetPatamRealValueAsUnicode(CondNode, "Param0",TermIns);
    return nodeprop==evt->GetTimerName();
  }
  return false;
}

bool Condition_HasSubStr(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
    string  nodeprop = Sce.GetPatamRealValue(CondNode, "Param0",TermIns);
    string  nodeprop1 = Sce.GetPatamRealValue(CondNode, "Param1",TermIns);
    string::size_type pos=nodeprop.find(nodeprop1);
    return pos != string::npos;
}

bool Condition_IsFinalMarked(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
    return TermIns.FinalMark;
}

bool Condition_IsToTagEqual(Scenario &Sce, TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
    osip_message_t *pomt=TermIns.GetCurrentMsg(evt);
    if (!pomt) return false;

    osip_generic_param_t *tag=NULL;
    if (pomt->to){
	osip_to_get_tag (pomt->to, &tag);
    }
    if (!tag) return false;

    string  nodeprop = Sce.GetPatamRealValue(CondNode, "Param0",TermIns);

    return strcmp(tag->gvalue,nodeprop.c_str())==0;

}

WX_DECLARE_STRING_HASH_MAP(SttConditionCallback, CondDriverHash);
CondDriverHash gSttConditionDrivers;

void initCondDrivers(void){
	gSttConditionDrivers[wxT("IsRequest")]=Condition_IsRequest;
	gSttConditionDrivers[wxT("IsAck")]=Condition_IsAck;
	gSttConditionDrivers[wxT("HasSubStr")]=Condition_HasSubStr;
	gSttConditionDrivers[wxT("IsUidEqual")]=Condition_IsUidEqual;
	gSttConditionDrivers[wxT("IsToTagEqual")]=Condition_IsToTagEqual;
	gSttConditionDrivers[wxT("IsEventNameEqual")]=Condition_IsEventNameEqual;
	gSttConditionDrivers[wxT("IsTimerNameEqual")]=Condition_IsTimerNameEqual;
	gSttConditionDrivers[wxT("HasHead")]=Condition_HasHead;
	gSttConditionDrivers[wxT("IsAllTermRegisted")]=Condition_IsAllTermRegisted;
	gSttConditionDrivers[wxT("IsResponseFor")]=Condition_IsResponseFor;
	gSttConditionDrivers[wxT("IsRspStateEqual")]=Condition_IsRspStateEqual;
	gSttConditionDrivers[wxT("IsVaribleEqual")]=Condition_IsVaribleEqual;
	gSttConditionDrivers[wxT("IsFinalMarked")]=Condition_IsFinalMarked;
}

int SttActionCmp(const void *p, const void *q){
	SttActionDriver *p1,*q1;
	p1 = (SttActionDriver *)p;
	q1 = (SttActionDriver *)q;
	return p1->DriverName.CmpNoCase(q1->DriverName);
}

int SttCondCmp(const void *p, const void *q){
	SttConditionDriver *p1,*q1;
	p1 = (SttConditionDriver *)p;
	q1 = (SttConditionDriver *)q;
	return p1->DriverName.CmpNoCase(q1->DriverName);
}

void SttActionDriverInit(void){
	InitActionDrivers();
	initCondDrivers();
	//qsort((void*)gSttActionDrivers,sizeof(gSttActionDrivers)/sizeof(SttActionDriver),
	//		sizeof(SttActionDriver),SttActionCmp);

	//qsort((void*)gSttConditionDrivers,sizeof(gSttConditionDrivers)/sizeof(SttConditionDriver),
	//		sizeof(SttConditionDriver),SttCondCmp);
}

Scenario::Scenario(){
	doc=NULL;
	NeedTermNum=1;
	EndOnOsipTimeout=true;
	RunDefaultRule=true;
	NeedRegiste=false;
	AllowAutoAck=true;
	context=NULL;
	EventRules=TimerRules=RecvRules=VaribleRules=ConfigureRules=SendRules=InitActions=FinalRules=NULL;
}

void Scenario::GetRuleNodeSet(void){
  {
    xmlChar nF[200]="//Scenario//EventRules//Rule";
    EventRules= GetNodeSet(nF);
  }

  {
    xmlChar nF[200]="//Scenario//FinalRules//Rule";
    FinalRules= GetNodeSet(nF);
  }

  {
    xmlChar nF[200]="//Scenario//TimerRules//Rule";
    TimerRules = GetNodeSet(nF);
  }

  {
    xmlChar nF[200]="//Scenario//RecvRules//Rule";
    RecvRules= GetNodeSet(nF);
  }


  {
    xmlChar nF[200]="//Scenario//Varibles//Varible";
    VaribleRules= GetNodeSet(nF);
  }

  {
    xmlChar nF[200]="//Scenario//Configures//Configure";
    ConfigureRules= GetNodeSet(nF);
  }

  {
    xmlChar nF[200]="//Scenario//SendRules//Rule";
    SendRules= GetNodeSet(nF);
  }

  {
    xmlChar nF[200]="//Scenario//InitActions//Action";
    InitActions= GetNodeSet(nF);
  }
}

Scenario::~Scenario(){
  ConfigData.clear();

  if (FinalRules){
      xmlXPathFreeObject(FinalRules);
  }

  if (EventRules){
    xmlXPathFreeObject(EventRules);
  }

  if (TimerRules){
    xmlXPathFreeObject(TimerRules);
  }

  if (RecvRules){
    xmlXPathFreeObject(RecvRules);
  }

  if (VaribleRules){
    xmlXPathFreeObject(VaribleRules);
  }

  if (ConfigureRules){
    xmlXPathFreeObject(ConfigureRules);
  }

  if (SendRules){
    xmlXPathFreeObject(SendRules);
  }

  if (InitActions){
    xmlXPathFreeObject(InitActions);
  }

  if (context)  xmlXPathFreeContext(context);
  if (doc) xmlFreeDoc(doc);
}

xmlXPathObjectPtr Scenario::GetNodeSet (xmlChar *xpath){

	xmlXPathObjectPtr result=NULL;

	result = xmlXPathEvalExpression(xpath, context);
	/*if(xmlXPathNodeSetIsEmpty(result->nodesetval)){
		return NULL;
		}*/

	return result;
}


std::string Scenario::Conv2Std(const wxString& src){
  static wxMutex s_mutexProtectingConv;
  wxMutexLocker lock(s_mutexProtectingConv);
  std::string ret="";
  if (src.Length()>0){
      wxCSConv cs(wxT("GB2312"));
      ret= (const char*)src.mb_str(cs);
  }
  return ret;
}

bool Scenario::TestAndRunRule(TermControl& TermIns,SttEvt *evt, xmlNodePtr RuleNode,bool IsFinalRule){
    if (TermIns.pCallInfo->GetCallState()==CALL_CB_IDLE) return true;
	xmlChar *nodeprop = xmlGetProp(RuleNode, (const xmlChar*)"ExecuteTerm");
	xmlChar *fmprop = xmlGetProp(RuleNode, (const xmlChar*)"NoFinalMark");
	string ExeTerm;
	if (nodeprop){
        ExeTerm=(const char*)nodeprop;
	}
	bool NoFinalMark=(fmprop != NULL);
    xmlFree(nodeprop);
    xmlFree(fmprop);
	if (ExeTerm.size()>0){
		if ((strcmp(ExeTerm.c_str(), "*") ==0)){
			long NeedTerms=1;
			TermIns.pCallInfo->Varibles[wxT("NeedTerms")].ToLong(&NeedTerms);
			for (int i=0;i<NeedTerms;i++){
				int TermIndex = TermIns.pCallInfo->UserIndexStart + i;
				TermControl& t=*TermIns.GetController().GetTermCtrl(TermIndex);
				if (MatchRule(t,evt,RuleNode)){
					STT_TRACE(t.Uid,TL_MATCH_RULE,wxString::Format(_("Match Rule %s in Line:%ld"),Identifier.c_str(),xmlGetLineNo(RuleNode)));
					t.pCallInfo->LogString(wxString::Format(_("Match Rule %s in Line:%ld"),Identifier.c_str(),xmlGetLineNo(RuleNode)));
					if (!ExecuteRuleActions(t,evt,RuleNode)){
						return false;
					}
					else{
					    if ((IsFinalRule) &&(!NoFinalMark)){
                            t.FinalMark = true;
					    }
					}
				}
			}
			return true;
		}
		else{
			int TermIndex=atoi(ExeTerm.c_str())+TermIns.pCallInfo->UserIndexStart;
			TermControl& t=*TermIns.GetController().GetTermCtrl(TermIndex);
			if (MatchRule(t,evt,RuleNode)){
				STT_TRACE(t.Uid,TL_MATCH_RULE,wxString::Format(_("Match Rule %s in Line:%ld"),Identifier.c_str(),xmlGetLineNo(RuleNode)));
				if (!ExecuteRuleActions(t,evt,RuleNode)){
					return false;
				}
			}
                        return true;
		}
	}
	else if (MatchRule(TermIns,evt,RuleNode)){
		STT_TRACE(TermIns.Uid,TL_MATCH_RULE,wxString::Format(_("Match Rule %s in Line:%ld"),Identifier.c_str(),xmlGetLineNo(RuleNode)));
		return ExecuteRuleActions(TermIns,evt,RuleNode);
	}
	return false;
}

void Scenario::SetIdentifier(wxString v){
	Identifier = v;
	wxString temp(wxConvCurrent->cWX2WC((const wxChar*)v),wxConvUTF8);
	xmlSetProp(identnode, (const xmlChar*)"Identifier", (const xmlChar*)(const char*)temp.c_str());
	xmlSaveFormatFile((const char*)filename.c_str(),doc,0);
}

int Scenario::ProcessSttEvt(TermControl& TermIns,SttEvt *evt){
  int MatchCount=0;
  switch (evt->GetEvtType()){
  case STTEVT_SCEARIO_FINISH:
  case STTEVT_CASE_FINISH:
      {
	  xmlXPathObjectPtr result = FinalRules;
	  if (result){
	      xmlNodeSetPtr nodeset;
	      nodeset = result->nodesetval;
	      for (int i=0; i<nodeset->nodeNr;i++){
		  if (TestAndRunRule(TermIns,evt,nodeset->nodeTab[i],true)){
		      MatchCount++;
		  }
	      }
	  }
      }
      break;
  case STTEVT_TERM_REGSTATE_CHANGE:
  case STTEVT_CASE_START:
  	{
      xmlXPathObjectPtr result = EventRules;
      if (result){
	xmlNodeSetPtr nodeset;
	nodeset = result->nodesetval;
	for (int i=0; i<nodeset->nodeNr;i++){
	  if (TestAndRunRule(TermIns,evt,nodeset->nodeTab[i])){
	    MatchCount++;
	  }
	}
      }
    }
    break;
  case STTEVT_TIMEROUT_EVENT:
    {
      xmlXPathObjectPtr result = TimerRules;
      if (result){
	xmlNodeSetPtr nodeset;
	nodeset = result->nodesetval;
	for (int i=0; i<nodeset->nodeNr;i++){
	  if (TestAndRunRule(TermIns,evt,nodeset->nodeTab[i])){
	    MatchCount++;
	  }
	}
      }
    }
    break;
  case STTEVT_OSIP_EVENT:
    {
	osip_message_t *pomt=evt->GetOsipMsgPtr();
	if (MSG_IS_RESPONSE_FOR(pomt, "INVITE")&&
	    ((MSG_TEST_CODE(pomt, 183) || MSG_TEST_CODE(pomt, 180)))){
	    osip_dialog_t *dialog;
	    dialog = TermIns.GetDialog(pomt);
	    if (dialog==NULL) //NO EXISTING DIALOG
		{
		    osip_dialog_init_as_uac(&dialog, pomt);
		    //osip_dialog_update_route_set_as_uas
		    TermIns.AddDialog(dialog);
		}
	}
	if (MSG_IS_RESPONSE_FOR(pomt, "SUBSCRIBE")&& (MSG_TEST_CODE(pomt, 200))){
	    osip_dialog_t *dialog;
	    dialog = TermIns.GetDialog(pomt);
	    if (dialog==NULL) //NO EXISTING DIALOG
		{
		    osip_dialog_init_as_uac(&dialog, pomt);
		    //osip_dialog_update_route_set_as_uas
		    TermIns.AddDialog(dialog);
		}
	}

	if (MSG_IS_RESPONSE_FOR(pomt,"REGISTER")){
	    if (!MSG_TEST_CODE(pomt,100)){
            if (MSG_TEST_CODE(pomt,200)){
                const char* UaTag="expires";
                osip_header_t *dest=NULL;
                osip_transaction_t *t = evt->GetOsipTransPtr();
                if (t){
                if (osip_message_header_get_byname(t->orig_request,UaTag,0,&dest)>=0){
                    if (dest){
                        if (atoi(dest->hvalue) == 0){
                            TermIns.SetRegisted(false);
                        }
                        else{
                            TermIns.SetRegisted(true);
                        }
                    }
                    else{
                        STT_TRACE(TermIns.Uid,TL_ERROR,wxT("Register without Expire!!"));
                        TermIns.SetRegisted(false);
                    }
                }
                }
            }
            else{
                TermIns.SetRegisted(false);
            }
	    }
	}

	if (MSG_TEST_CODE(pomt, 407)){
	    /*Store nonce*/
	    osip_proxy_authenticate_t *dest=NULL;
	    osip_message_get_proxy_authenticate(pomt, 0, &dest);
	    if (dest){
		char* nonce=osip_www_authenticate_get_nonce(dest);
		if (nonce){
		    TermIns.lastnonce=nonce;
		    TermIns.lastAlgorithm = osip_www_authenticate_get_algorithm(dest);
		    if (TermIns.lastnonce.size()>2){
			if (TermIns.lastnonce[0]=='"'){
			    TermIns.lastnonce.erase(0,1);
			}
			if (TermIns.lastnonce[TermIns.lastnonce.size()-1]=='"'){
			    TermIns.lastnonce.erase(TermIns.lastnonce.size()-1,1);
			}
		    }
		}
	    }
	}


	if (MSG_TEST_CODE(pomt, 401)){
	    /*Store nonce*/
	    osip_www_authenticate_t *dest=NULL;
	    osip_message_get_www_authenticate (pomt, 0, &dest);
	    if (dest){
		char* nonce=osip_www_authenticate_get_nonce(dest);
		if (nonce){
		    TermIns.lastnonce=nonce;
		    TermIns.lastAlgorithm = osip_www_authenticate_get_algorithm(dest);
		    if (TermIns.lastnonce.size()>2){
			if (TermIns.lastnonce[0]=='"'){
			    TermIns.lastnonce.erase(0,1);
			}
			if (TermIns.lastnonce[TermIns.lastnonce.size()-1]=='"'){
			    TermIns.lastnonce.erase(TermIns.lastnonce.size()-1,1);
			}
		    }
		}
	    }

	    osip_header_t *ph=NULL;
	    osip_message_header_get_byname(pomt,"Security-Server",0,&ph);
	    if (ph){
		wxString ParamValue=GetOsipHeadParamValueByName(ph,"port-s");
		if (ParamValue.IsNumber()){
		    long rp=0;
		    ParamValue.ToLong(&rp);
		    TermIns.RemotePort=rp;
		}
	    }
	}

	xmlXPathObjectPtr result = RecvRules;
	if (result){
	    xmlNodeSetPtr nodeset;
	    nodeset = result->nodesetval;
	    for (int i=0; i<nodeset->nodeNr;i++){
		if (TestAndRunRule(TermIns,evt,nodeset->nodeTab[i])){
		    MatchCount++;
		}
	    }
	}
    }
    break;
  default:
      {
	  break;
      }
  }
  return MatchCount;
}

wxString Scenario::GetOsipHeadParamValueByName(osip_header_t *ph,const char*paramname){
    string rt="";
    if ((ph)&&(ph->hvalue)){
	string v(ph->hvalue);
	string n(paramname);
	n+="=";
	string::size_type pos = v.find(n);
	if (pos != string::npos){
	    string v1=v.substr(pos+n.size());
	    pos=v1.find(";");
	    if (pos==string::npos){
		pos=v1.size();
	    }
	    rt=v1.substr(0,pos);
	}
    }
    return STT_LStr(rt.c_str());
}

xmlNodePtr Scenario::GetConditionsNode(xmlNodePtr RuleNode){
	xmlNode *c;
	for (c = RuleNode->children; c; c= c->next) {
        if (c->type == XML_ELEMENT_NODE) {
			if (xmlStrcmp(c->name, (const xmlChar *) "Conditions") ==0) {
				return c;
			}
        }
    }
	return NULL;
}

xmlNodePtr Scenario::GetActionsNode(xmlNodePtr RuleNode){
	xmlNode *c;
	for (c = RuleNode->children; c; c= c->next) {
        if (c->type == XML_ELEMENT_NODE) {
			if (xmlStrcmp(c->name, (const xmlChar *) "Actions") ==0) {
				return c;
			}
        }
    }
	return NULL;
}

bool Scenario::MatchCondition(TermControl& TermIns,SttEvt *evt,xmlNodePtr CondNode){
	bool ret=false;
        SttConditionDriver stDriver;
	//SttConditionDriver *driver;
	xmlChar *nodeprop = xmlGetProp(CondNode, (const xmlChar*)"Cmd");
	xmlChar *traceprop = xmlGetProp(CondNode, (const xmlChar*)"Trace");
	if (nodeprop){
		bool IsNot=false;
		stDriver.DriverName=wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent);
		xmlFree(nodeprop);
		if (stDriver.DriverName.Mid(0,1) == wxT("@")){
			IsNot=true;
			stDriver.DriverName.Remove(0,1);
		}
		if ((gSttConditionDrivers.find(stDriver.DriverName) != gSttConditionDrivers.end())){
			if (IsNot){
				ret = !gSttConditionDrivers[stDriver.DriverName](*this,TermIns,evt,CondNode);
			}
			else{
				ret = gSttConditionDrivers[stDriver.DriverName](*this,TermIns,evt,CondNode);
			}

		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Unknown Condition Cmd:")+stDriver.DriverName);
		}
	}
        if (traceprop){
            STT_TRACE(TermIns.Uid,TL_MESSAGE,wxString::Format(_("Try Match Condition in line %d return %d"),
                        xmlGetLineNo(CondNode),ret));
        }
	return ret;
}

bool Scenario::MatchRule(TermControl& TermIns,SttEvt *evt,xmlNodePtr RuleNode){
	xmlNodePtr Conds=GetConditionsNode(RuleNode);
	if (Conds != NULL){
		xmlNode *Condition;
		for (Condition = Conds->children; Condition; Condition= Condition->next) {
	        if (Condition->type == XML_ELEMENT_NODE) {
				if (!MatchCondition(TermIns,evt,Condition)){
					return false;
				}
	        }
	    }
	}
	return true;
}

bool Scenario::ReLoad(){
    return LoadFromFile(filename);
}

bool Scenario::IsSourceModified(){
    return lastmodifytime!=wxFileName(filename).GetModificationTime();
}

wxString Scenario::GetConfigValue(const wxString&key){
  if ((ConfigData.find(key) != ConfigData.end()) &&(!ConfigData[key].IsEmpty()))  return ConfigData[key];
	if ((wxGetApp().m_ScenariosManager->DefaultScenario) &&
		(wxGetApp().m_ScenariosManager->DefaultScenario->GetMap()->find(key) !=
			wxGetApp().m_ScenariosManager->DefaultScenario->GetMap()->end()))
			return (*wxGetApp().m_ScenariosManager->DefaultScenario->GetMap())[key];
	/*wxString ret;
	wxConfigBase *pConfig = wxConfigBase::Get();
	pConfig->SetPath(GLOBAL_KEY);
	if (pConfig->Read(key,&ret)) return ret;*/

	return wxT("");
}

void Scenario::SetConfigValue(const wxString&key, const wxString&value){
	ConfigData[key] = value;
}

wxString Scenario::RealValue(wxString v, TermControl& TermIns,wxString Sep,xmlNodePtr Node,Scenario* s){
        int pos=v.find(wxT(" "));
	if (pos<=0) return v;
	wxString Item=v.Left(pos);
	wxString Key=v.Mid(pos+1,v.Length());
	if (Item==wxT("Configure")){
		return GetConfigValue(Key);
	}
	else if (Item==wxT("Varible")){
		return TermIns.pCallInfo->Varibles[Key];
	}
	else if ((Item==wxT("Genurate"))||
        (Item==wxT("Encrypt"))){
		Key.Trim(false);
		pos=Key.find(Sep);
		wxString format=wxT("");
		if (pos>0){
			format=Key.Left(pos);
			wxString tmpfmt=format;

			format=TermIns.GetVaribleValue(tmpfmt);
			if (format.IsEmpty() || (format == tmpfmt)){
			  format=GetConfigValue(tmpfmt);
			}
			if (format.IsEmpty()){
			  format = tmpfmt;
			}

			Key=Key.Mid(pos+Sep.size(),Key.Length());
			int reppos=format.find(wxT("%s"));
			while (reppos>=0){
				Key.Trim(false);
				pos=Key.find(wxT(" "));
				if (pos<0) pos=Key.Length();
				wxString ValueKey=Key.Left(pos);
				Key=Key.Mid(pos+1,Key.Length());
				if (ValueKey.Length()<=0){
				  STT_TRACE(TermIns.Uid,TL_ERROR,_("Bad Format or Params Num in ")+v);
				  return wxT("");
				}
				wxString rv=TermIns.GetVaribleValue(ValueKey);
				if (!rv.IsEmpty()){
				  format.Replace(wxT("%s"),rv,false);
				}
				else if ((ValueKey)==wxT("UID")){
					format.Replace(wxT("%s"),wxString::Format(wxT("%06d"),TermIns.Uid),false);
				}
				else if ((ValueKey)==wxT("__LINE__")){
				    if (TermIns.pCallInfo->SendRuleLineNo>=0){
					format.Replace(wxT("%s"),wxString::Format(wxT("%ld"),TermIns.pCallInfo->SendRuleLineNo),false);
				    }
				    else{
					format.Replace(wxT("%s"),_("No Line No Info"),false);
				    }
				}
				else if ((ValueKey)==wxT("__FILE__")){
				    if (s){
					format.Replace(wxT("%s"),s->filename,false);
				    }
				    else{
					format.Replace(wxT("%s"),_("No Filename Info"),false);
				    }
				}
				else if ((ValueKey)==wxT("CALC_RESPONSE")){
					std::string rsp,auts;
					TermIns.CaleResponse(rsp,auts);
					format.Replace(wxT("%s"), STT_LStr((char*)rsp.c_str()),false);
				}
				else if ((ValueKey)==wxT("FIRST_UID_IN_CALL")){
					format.Replace(wxT("%s"),wxString::Format(wxT("%06d"),TermIns.pCallInfo->UserIndexStart),false);
				}
				else if ((ValueKey)==wxT("LOCALPORT")){
				    format.Replace(wxT("%s"),wxString::Format(wxT("%d"),TermIns.GetLocalPort()),false);
				}
				else if ((ValueKey)==wxT("REMOTEPORT")){
				     if (TermIns.RemotePort==0){
						format.Replace(wxT("%s"),wxString::Format(wxT("%d"),5060),false);
					}
				else{
				    format.Replace(wxT("%s"),wxString::Format(wxT("%d"),TermIns.RemotePort),false);
					}
				}
				else if ((ValueKey)==wxT("LOCALIP")){
					format.Replace(wxT("%s"),wxGetApp().GetHostName(),false);
				}
				else if ((ValueKey)==wxT("LOCALIPU32")){
				    format.Replace(wxT("%s"),wxString::Format(wxT("%ld"),(long)inet_addr(wxGetApp().GetHostName().mb_str())),false);
				}
				else if ((ValueKey)==wxT("TICKCOUNT")){
				    format.Replace(wxT("%s"),wxString::Format(wxT("%ld"),(long)time(NULL)),false);
				}
				else if ((ValueKey)==wxT("STATIC")){
					static int SEED=1;
					format.Replace(wxT("%s"),wxString::Format(wxT("%06d%03d"),TermIns.Uid,SEED++),false);
				}
				else if ((ValueKey)==wxT("STATIC_CSEQ_SEED")){
					static int CSEQ_SEED=1;
					format.Replace(wxT("%s"),wxString::Format(wxT("%d"),CSEQ_SEED++),false);
				}
				else if ((ValueKey)==wxT("STATIC_VIA_SEED")){
					static int VIA_SEED=1;
					format.Replace(wxT("%s"),wxString::Format(wxT("%d"),VIA_SEED++),false);
				}
				else if ((ValueKey)==wxT("RANDOM")){
					format.Replace(wxT("%s"),wxString::Format(wxT("%u"),osip_build_random_number()),false);
				}
				else {
				    format.Replace(wxT("%s"),GetConfigValue(ValueKey),false);
				}
				reppos=format.find(wxT("%s"));
			}
		}
		if (Item==wxT("Encrypt")){
            string input = Conv2Std(format);
            char output[255]="";
            unsigned int len=254;
            aes_ims_encrypt(0xFFFFFFFF, (unsigned char*)input.c_str(), (unsigned char*)output, input.length()+1, &len);
            if (len<=0){
                STT_TRACE(-1,TL_ERROR,wxString::Format(_("Encrypt return error length:%d"),len));
            }
            else{
                format = STT_LStr(output);
            }
		}
		return format;

	}
	else if (Item==wxT("Calc")){
		Key.Trim(false);
		pos=Key.find(wxT(" "));
		if (pos>0){
			wxString format=Key.Left(pos);
			Key=Key.Mid(pos+1,v.Length());
			pos=Key.find(wxT(" "));
			if (pos>0){
			  wxString Op=Key.Left(pos);
			  Key=Key.Mid(pos+1,v.Length());

			  wxString fmt=wxT("%06u");
			  pos = Key.find(wxT(" "));
			  if (pos>0){
			      fmt = Key.Mid(pos+1,v.Length());
			      Key=Key.Left(pos);
			  }

			  long l1=0, l2=0;
			  format = RealValue(wxString(wxT("Genurate %s "))+format,TermIns);
			  if (format.IsNumber()){
			      format.ToLong(&l1);
			  }
			  else{
			      return wxT("");
			  }
			  Key.ToLong(&l2);
			  if (Op == wxT("+")){
			    return wxString::Format(fmt,l1+l2);
			  }
			  else if (Op == wxT("-")){
			    return wxString::Format(fmt,l1-l2);
			  }
			  else if (Op == wxT("*")){
			    return wxString::Format(fmt,l1*l2);
			  }
			  else if (Op == wxT("/")){
			    return wxString::Format(fmt,l1/l2);
			  }
			}
		}
	}
	else if (Item==wxT("Random")){
		Key.Trim(false);
		Key+=wxT(" ");
		wxArrayString allvalue;
		pos=Key.find(wxT(" "));
		while (pos>0){
			wxString format=Key.Left(pos);
			format = RealValue(wxString(wxT("Genurate %s "))+format,TermIns);
			format.Trim(false);
			format+=wxT(" ");
			int subpos=format.find(wxT(" "));
			while (subpos>0){
			  wxString subformat=format.Left(subpos);
			  format=format.Mid(subpos+1,format.Length());
			  subformat.Trim(false);
			  if (subformat.size()>0){
			    allvalue.push_back(subformat);
			  }
			  subpos=format.find(wxT(" "));
			}
			Key=Key.Mid(pos+1,Key.Length());
			pos=Key.find(wxT(" "));
		}
		if (allvalue.size()>0){
		  static int valueseed=0;
		  //srand (time (NULL));
		  //int i=rand() % allvalue.size();
		  //STT_TRACE(TermIns.Uid,TL_ERROR,wxString::Format(_("Random return %d Total:%d %d"),i,allvalue.size(),rand()));
		  int i = (valueseed++)%allvalue.size();
		  return allvalue[i];
		}

	}
	else{
		return v;
		//STT_TRACE(TermIns.Uid,TL_ERROR,_("Unknown Value Item :")+Item);
	}
	return wxT("");
}

void Scenario::InitTermVaribles(StrStrHash &Vars, bool ForceInit){
    //Vars.clear();

	if ((wxGetApp().m_ScenariosManager->DefaultScenario) &&
	    (this != wxGetApp().m_ScenariosManager->DefaultScenario)){
	    wxGetApp().m_ScenariosManager->DefaultScenario->InitTermVaribles(Vars,ForceInit);
	}

	xmlXPathObjectPtr result = VaribleRules;
	if (result){
		xmlNodeSetPtr nodeset;
		nodeset = result->nodesetval;
		for (int i=0; i<nodeset->nodeNr;i++){
			xmlChar *varname = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"name");
			xmlChar *vardefault = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"default");
			xmlChar *scope = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"scope");
			xmlChar *clearOnSceInit = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"NotClearOnSceInit");
			if (varname){
				wxString VarName = XmlChar2Unicode(varname);
				xmlFree(varname);
				wxString VarDefault = wxT("");
				wxString Scope =wxT("");
				if (scope) {
					Scope = XmlChar2Unicode(scope);
					xmlFree(scope);
				}
				if (vardefault){
				  VarDefault=XmlChar2Unicode(vardefault);
				  xmlFree(vardefault);
				}
				//printf("name:%s scope:%s default:%s",(const char*)VarName.mb_str(wxConvUTF8),
				//       (const char*)Scope.mb_str(wxConvUTF8),
				//       (const char*)VarDefault.mb_str(wxConvUTF8));
				if (Scope == wxT("Term")){
				    if ((Vars.find(VarName)==Vars.end()) || ForceInit || ((!clearOnSceInit) || (strcmp((const char*)clearOnSceInit,"1")!=0))){
					Vars[VarName] = VarDefault;
					//STT_TRACE
				    }
				}
				if (clearOnSceInit)   xmlFree(clearOnSceInit);
			}
		}
	}
}

void Scenario::DumpConfig(){
  for(StrStrHash::iterator iter = ConfigData.begin(); iter != ConfigData.end(); iter++)
  {
    printf("%s: %s\n", (const char*) iter->first.mb_str(wxConvUTF8), (const char*)iter->second.mb_str(wxConvUTF8));
  }
}

void Scenario::InitCallVaribles(StrStrHash &Vars){
	Vars.clear();

	if ((wxGetApp().m_ScenariosManager->DefaultScenario) &&
	    (this != wxGetApp().m_ScenariosManager->DefaultScenario)){
		wxGetApp().m_ScenariosManager->DefaultScenario->InitCallVaribles(Vars);
	}

	xmlXPathObjectPtr result = VaribleRules;
	if (result){
		xmlNodeSetPtr nodeset;
		nodeset = result->nodesetval;
		for (int i=0; i<nodeset->nodeNr;i++){
			xmlChar *varname = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"name");
			xmlChar *vardefault = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"default");
			xmlChar *scope = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"scope");
			if (varname){
				wxString VarName = XmlChar2Unicode(varname);
				xmlFree(varname);
				wxString VarDefault = wxT("");
				wxString Scope =wxT("");
				if (scope) {
					Scope = XmlChar2Unicode(scope);
					xmlFree(scope);
				}
				if (vardefault) {
				  VarDefault=XmlChar2Unicode(vardefault);
				  xmlFree(vardefault);
				}
				if (Scope != wxT("Term")){
					Vars[VarName] = VarDefault;
				}
			}
		}
	}

	if (this != wxGetApp().m_ScenariosManager->DefaultScenario){
		Vars[wxT("NeedTerms")] = wxString::Format(wxT("%d"),NeedTermNum);
		if (NeedRegiste) Vars[wxT("NeedRegisted")] = wxT("1");
		else Vars[wxT("NeedRegisted")] = wxT("0");
	}
}

wxString Scenario::GetPatamRealValueAsUnicode(xmlNodePtr Node, const char *v,TermControl& TermIns,Scenario* s){
    if ((v) &&(strlen(v)>0)){
	xmlChar *value = xmlGetProp(Node, (const xmlChar*)v);
	if (value){
	    wxString V=XmlChar2Unicode(value);
	    xmlFree(value);
	    wxString Seprate=wxT(" ");
	    xmlChar *sep = xmlGetProp(Node, (const xmlChar*)"Seprate");
	    if (sep){
		Seprate=XmlChar2Unicode(sep);
		xmlFree(sep);
	    }
            if (Seprate==wxT(" ")){
                if (V.Find(wxT("|"))>0){
                    Seprate=wxT("|");
                }
            }
	    wxString Rv=RealValue(V,TermIns,Seprate,Node,s);
	    return Rv;
	}
	else{
	    return wxT("");
	}
    }
    else{
	xmlNode *c;
	wxString V=wxT("");
	for (c = Node->children; c; c= c->next) {
	    if (c->type == XML_CDATA_SECTION_NODE){
		V+=XmlChar2Unicode(c->content);
		return V;
	    }
	}
    }
    return wxT("");
}

std::string Scenario::GetPatamRealValue(xmlNodePtr Node, const char *v,TermControl& TermIns,Scenario* s){
    return Conv2Std(GetPatamRealValueAsUnicode(Node,v,TermIns,s));
}

void Scenario::InitConfigValue(void){
	ConfigData.clear();

	/*wxConfigBase *pConfig = wxConfigBase::Get();
	pConfig->SetPath(GLOBAL_KEY);
	long Index;
	wxString key;
	if (pConfig->GetFirstEntry(key,Index)){
		do{
			wxString value=wxT("");
			pConfig->Read(key,&value);
			ConfigData[key]=value;
		}
		while (pConfig->GetNextEntry(key,Index));
	}*/

	/*StrStrHash*pdefault = wxGetApp().m_ScenariosManager.DefaultScenario->GetMap();
	if (pdefault){
	  for(StrStrHash::iterator iter = (*pdefault).begin(); iter != (*pdefault).end(); iter++)
	    {
	      ConfigData[(*iter).first] = iter->second;
	    }
	    }*/

	xmlXPathObjectPtr result = ConfigureRules;
	if (result){
		xmlNodeSetPtr nodeset;
		nodeset = result->nodesetval;
		for (int i=0; i<nodeset->nodeNr;i++){
			xmlChar *varname = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"key");
			xmlChar *vardefault = xmlGetProp(nodeset->nodeTab[i], (const xmlChar*)"value");
			if (varname){
				wxString VarName = XmlChar2Unicode(varname);
				xmlFree(varname);
				wxString VarDefault = wxT("");
				if (vardefault) {
				  VarDefault=XmlChar2Unicode(vardefault);
				  xmlFree(vardefault);
				}
				ConfigData[VarName] = VarDefault;
			}
		}
	}
}

bool Scenario::ExecuteSendRule(TermControl& TermIns,SttEvt *evt){
	xmlXPathObjectPtr result = SendRules;
	if (result){
		xmlNodeSetPtr nodeset;
		nodeset = result->nodesetval;
		for (int i=0; i<nodeset->nodeNr;i++){
			if (MatchRule(TermIns,NULL,nodeset->nodeTab[i])){
			  if (!ExecuteRuleActions(TermIns,evt,nodeset->nodeTab[i])){
			    return false;
			  }
			}
		}
	}
	return true;
}

bool Scenario::ExecuteRuleActions(TermControl& TermIns,SttEvt *evt,xmlNodePtr RuleNode){
	xmlNodePtr Actions=GetActionsNode(RuleNode);
	if (Actions!=NULL){
		xmlNode *Action;
		for (Action = Actions->children; Action; Action = Action->next) {
	        if (Action->type == XML_ELEMENT_NODE) {
		  if (!ExecuteAction(TermIns,evt,Action)){
		    STT_TRACE(TermIns.Uid,TL_ERROR,wxString::Format(_("Execute Rule Action %s in Line:%ld Fail"),Identifier.c_str(),xmlGetLineNo(Action)));
		    TermIns.OnScenarioEnd(false,_("Execute Action Fail"));
		    return false;
		  }
	        }
	    }
	}
	return true;
}

bool Scenario::ExecuteAction(TermControl& TermIns,SttEvt *evt,xmlNodePtr ActionNode){
	SttActionDriver stDriver;
	//SttActionDriver *driver;
	xmlChar *nodeprop = xmlGetProp(ActionNode, (const xmlChar*)"Cmd");
	if (nodeprop){
		stDriver.DriverName=wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent);
		xmlFree(nodeprop);

		if (gSttActionDrivers.find(stDriver.DriverName) != gSttActionDrivers.end()){
			return gSttActionDrivers[stDriver.DriverName](*TermIns.pCallInfo->pCurSce,TermIns,evt,ActionNode);
		}
		else{
			STT_TRACE(TermIns.Uid,TL_ERROR,_("Unknown Action:")+stDriver.DriverName);
		}
	}
	return false;
}

void Scenario::ExecuteDefaultAction(TermControl& TermIns){
	xmlXPathObjectPtr result = InitActions;
	if (result){
		xmlNodeSetPtr nodeset;
		nodeset = result->nodesetval;
		for (int i=0; i<nodeset->nodeNr;i++){
			ExecuteAction(TermIns,NULL,nodeset->nodeTab[i]);
		}
	}
}

bool Scenario::LoadFromFile(wxString fname){
    wxGetApp().DoLog(wxString::Format(wxT("Try to load case from %s\n"),fname.c_str()));

    identnode=NULL;
    filename=fname;

    if (ConfigureRules){
      xmlXPathFreeObject(ConfigureRules);
      ConfigureRules=NULL;
    }
    if (SendRules){
      xmlXPathFreeObject(SendRules);
      SendRules=NULL;
    }
    if (InitActions){
      xmlXPathFreeObject(InitActions);
      InitActions=NULL;
    }

    if (FinalRules){
      xmlXPathFreeObject(FinalRules);
      FinalRules=NULL;
    }

    if (EventRules){
      xmlXPathFreeObject(EventRules);
      EventRules=NULL;
    }

    if (TimerRules){
      xmlXPathFreeObject(TimerRules);
      TimerRules=NULL;
    }

    if (RecvRules){
      xmlXPathFreeObject(RecvRules);
      RecvRules=NULL;
    }

    if (VaribleRules){
      xmlXPathFreeObject(VaribleRules);
      VaribleRules=NULL;
    }


    if (context)  xmlXPathFreeContext(context);

    if (doc){
	xmlFreeDoc(doc);
    }
    doc = xmlReadFile(fname.mb_str(), NULL, 0);
    /* check if parsing suceeded */
    if (doc == NULL) {
        wxGetApp().DoLog(wxString::Format(_T("Failed to parse %s\n"), STT_LStr(fname.c_str())));
    }
    else{
	lastmodifytime=wxFileName(fname).GetModificationTime();
	xmlNodePtr cur;
	cur = xmlDocGetRootElement(doc);
	xmlChar *nodeprop = xmlGetProp(cur, (const xmlChar*)"Identifier");
	if (nodeprop!=NULL)   {
	    identnode=cur;
	    Identifier =wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent);
	    xmlFree(nodeprop);
	}
	nodeprop = xmlGetProp(cur, (const xmlChar*)"NeedTerms");
	if (nodeprop!=NULL) {
	    long v;
	    wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent).ToLong(&v);
	    xmlFree(nodeprop);
	    NeedTermNum = v;
	}

		nodeprop = xmlGetProp(cur, (const xmlChar*)"DefaultRule");
		if (nodeprop!=NULL)
		{
			long v;
			wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent).ToLong(&v);
			xmlFree(nodeprop);
			RunDefaultRule = (v==1);
		}
		
		nodeprop = xmlGetProp(cur, (const xmlChar*)"AllowAutoAck");
		if (nodeprop!=NULL)
		{
			AllowAutoAck = !(wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent)== wxT("0"));
			xmlFree(nodeprop);
		}

		nodeprop = xmlGetProp(cur, (const xmlChar*)"NeedRegisted");
		if (nodeprop!=NULL)
		{
			NeedRegiste =(wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent)== wxT("1"));
			xmlFree(nodeprop);
		}

		timeout=60;
		nodeprop = xmlGetProp(cur, (const xmlChar*)"Timeout");
		if (nodeprop!=NULL)
		{
		    long v=60;
		    (wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent)).ToLong(&v);
		    timeout=v;
		    xmlFree(nodeprop);
		}

		nodeprop = xmlGetProp(cur, (const xmlChar*)"FailOnSipTimeout");
		if (nodeprop!=NULL)
		{
			EndOnOsipTimeout =(wxString(wxConvUTF8.cMB2WC((const char*)nodeprop),*wxConvCurrent)== wxT("1"));
			xmlFree(nodeprop);
		}

		context = xmlXPathNewContext(doc);
		GetRuleNodeSet();
		InitConfigValue();
	}
	return (doc != NULL);
}

/**
  * 场景管理器的构造函数
  *
  * 读取所有的场景
  *
  */
ScenariosManager::ScenariosManager(){
	DefaultScenario=NULL;
	wxFileName def(wxGetCwd()+wxFileName::GetPathSeparator()+_T("default.xml"));
	//def.InsertDir(0,wxGetCwd());
	if (def.FileExists()){
		DefaultScenario = new Scenario();
		DefaultScenario->LoadFromFile(def.GetFullPath());
	}
        else{
                wxGetApp().DoLog(wxString::Format(wxT("File %s doest not exists!\n"),def.GetFullPath().c_str()));
        }

	wxFileName Base(wxGetCwd()+wxFileName::GetPathSeparator()+_T("scenarios"));
	//wxSafeShowMessage(wxT("sdf"),Base.GetFullPath());
	//Base.InsertDir(0,wxGetCwd());
	LoadScenariosFrom(Base.GetFullPath());
}

void ScenariosManager::LoadScenariosFrom(const wxString& Dir){
    wxDir dir(Dir);
    if ( !dir.IsOpened() ){
	// deal with the error here - wxDir would already log an error message
        // explaining the exact reason of the failure
        return;
    }

    wxString filename;
    bool cont = dir.GetFirst(&filename, _T("*.xml"));
    while ( cont )  {
        wxFileName fname(Dir+ wxFileName::GetPathSeparator()+ filename);
	//fname.InsertDir(0,Dir);

	Scenario*p=new Scenario();
	wxString fullpath=fname.GetFullPath();
	p->LoadFromFile(fullpath);
	if (p->GetIdentifier().IsEmpty()){
	    wxLogWarning(_T("No Use Scenario %s,No Identifier!"), fullpath.c_str());
	    delete(p);
	}
	else{
	  AllScenarios.push_back(p);
	}

        cont = dir.GetNext(&filename);
    }
	sort(AllScenarios.begin(),AllScenarios.end(),less_ScenarioName);
}

int ScenariosManager::GetMaxTermNeeded(){
  ScPtrArray::iterator iter;
  int MaxTermNeed=0;
  for (iter=AllScenarios.begin();iter!=AllScenarios.end();iter++){
    Scenario*p = *iter;
    if (p->GetNeedTermNum()>MaxTermNeed){
      MaxTermNeed = p->GetNeedTermNum();
    }
  }
  return MaxTermNeed;
}

ScenariosManager::~ScenariosManager(){
	ScPtrArray::iterator iter;
	for (iter=AllScenarios.begin();iter!=AllScenarios.end();iter++){
		Scenario*p = *iter;
		delete(p);
	}
	AllScenarios.clear();
	if (DefaultScenario){
	    delete(DefaultScenario);
	    DefaultScenario=NULL;
	}
}

bool less_ScenarioName(Scenario* m1, Scenario* m2){
    wxString id1=m1->GetIdentifier();
    wxString id2=m2->GetIdentifier();
    return  id1< id2;
}

